# encoding: utf-8
from __future__ import unicode_literals

import datetime
import json

from django import template
from django.conf import settings
from django.db.models import Sum

register = template.Library()


@register.inclusion_tag('admin_highcharts/js.html', takes_context=True)
def highcharts_for_result(context, cl):
    def get_verbose_name(name):
        for item in cl.model._meta.fields:
            if item.name == name:
                return item.verbose_name
        try:
            func = getattr(cl.model_admin, name)
            return func.short_description
        except AttributeError:
            pass

    def get_attr(obj, name):
        if isinstance(obj, dict):
            if name in obj:
                return obj[name]
            return name
        else:
            try:
                return getattr(obj, name)
            except AttributeError:
                func = getattr(cl.model_admin, name)
                return func(obj)

    def get_names():
        category_name = cl.model_admin.list_display[0] if not hasattr(cl.model_admin,
                                                                      'chart_category_name') else cl.model_admin.chart_category_name
        if hasattr(cl.model_admin, 'chart_serial_names'):
            serial_names = cl.model_admin.chart_serial_names
        else:
            serial_names = []
            for name in cl.model_admin.list_display:
                if name == category_name:
                    continue
                serial_names.append(name)
        return category_name, serial_names

    def get_gmkb(bits):
        if bits > 1000000000:  # G
            return '%.2fgb' % (bits / 1000000000)
        elif bits > 1000000:  # M
            return '%.2fmb' % (bits / 1000000)
        elif bits > 1000:  # k
            return '%.2fkb' % (bits / 1000)
        return '%.2fb' % bits

    def get_gmkb2(bits):
        if bits > 1073741824:  # G
            return '%.2fgb' % (bits / 1073741824)
        elif bits > 1048576:  # M
            return '%.2fmb' % (bits / 1048576)
        elif bits > 1024:  # k
            return '%.2fkb' % (bits / 1024)
        return '%.2fb' % bits

    category_name, serial_names = get_names()
    chart_type = 'line' if not hasattr(cl.model_admin, 'chart_type') else cl.model_admin.chart_type
    chart_one = '0' if not hasattr(cl.model_admin, 'chart_one') else cl.model_admin.chart_one
    categories = []
    is_date = False
    if cl.result_list.count() > 0 and isinstance(get_attr(cl.result_list[0], category_name), datetime.datetime):
        is_date = True
    # for item in cl.result_list:
    #     categories.append(get_attr(item,category_name))
    series = []
    # for key in serial_names:
    #     data = []
    #     for item in cl.result_list:
    #         data.append(get_attr(item,key))
    #     series.append({
    #                    'name':get_verbose_name(key),
    #                    'data':data,
    #                    })
    if not hasattr(cl.model_admin, 'chart_key'):
        datas = {}
        for item in cl.result_list:
            if is_date:
                utc = get_attr(item, category_name)
                if settings.USE_TZ:
                    utc = utc + datetime.timedelta(hours=8)
                name = utc.strftime('%m-%d %H:%M')
            else:
                name = get_attr(item, category_name)
            if name not in categories:
                categories.append(name)
            for key in serial_names:
                dkey = u'%s' % get_verbose_name(key)
                if dkey not in datas:
                    datas[dkey] = []
                datas[dkey].append(get_attr(item, key))
        for key, data in datas.items():
            series.append({
                'name': key,
                'data': data,
            })
    else:
        chart_key = cl.model_admin.chart_key
        datas = {}
        billing = 0
        max_bits = 0
        min_bits = 0
        cqs = cl.result_list
        if chart_one == '1':
            cqs = cl.queryset.values('date').annotate(in_bits=Sum('in_bits'), out_bits=Sum('out_bits'))
        if len(serial_names) > 2 and cqs.count() > 0:
            point = round(cqs.count() * 0.05 + 1)
            if cl.result_list.first().port.direct == '0':
                qs = cqs.order_by('-in_bits')
                billing = get_attr(qs[point:point+1][0], 'in_bits')
                max_bits = get_attr(qs.first(), 'in_bits')
                min_bits = get_attr(qs.last(), 'in_bits')
            else:
                qs = cqs.order_by('-out_bits')
                billing = get_attr(qs[point:point+1][0], 'out_bits')
                max_bits = get_attr(qs.first(), 'out_bits')
                min_bits = get_attr(qs.last(), 'out_bits')
            qs = cqs.order_by('-date')
        else:
            qs = cqs
        for item in qs:
            if is_date:
                utc = get_attr(item, category_name)
                if isinstance(utc, datetime.datetime):
                    if settings.USE_TZ:
                        utc = utc + datetime.timedelta(hours=8)
                    name = utc.strftime('%m-%d %H:%M')
                else:
                    name = utc
            else:
                name = get_attr(item, category_name)
            if name not in categories:
                categories.append(name)
            for key in serial_names:
                dkey = u'%s - %s' % (get_attr(item, chart_key), get_verbose_name(key))
                if dkey not in datas:
                    datas[dkey] = []
                if key == 'billing':
                    datas[dkey].append(billing)
                else:
                    datas[dkey].append(get_attr(item, key))
        for key, data in datas.items():
            if is_date:
                data.reverse()
            series.append({
                'name': key.replace('port', u'端口聚合').replace('billing', u'95%%: %s  最小: %s  最大: %s' % (get_gmkb(billing), get_gmkb(min_bits), get_gmkb(max_bits))),
                'data': data,
            })
    if is_date:
        categories.reverse()

    result = {
        'categories': categories,
        'series': series,
        'type': chart_type,
        'option': json.dumps(cl.model_admin.chart_option),
    }
    return result
